package de.gist.calldurationwatcher.activities;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import de.gist.calldurationwatcher.helper.CallLogFields;
import de.gist.calldurationwatcher.helper.CallLogHelper;
import de.gist.calldurationwatcher.helper.Utils;
import de.gist.calldurationwatcher.preferences.Preferences;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.CallLog;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.SimpleCursorAdapter;
import android.widget.TableRow;
import android.widget.TextView;

public class CallDurationWatcherActivity extends Activity {
	
	private static Uri CALLSURI = android.provider.CallLog.Calls.CONTENT_URI;
	private int freeMinutesSetting = 0;
	private int minutesLeft = 0;
	private ProgressBar timerProgress;
	private boolean firstStart;
	private Date contractStartDate;
	private HashMap<Date, Boolean> freeStates;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        try {
	        setContentView(R.layout.main);
	        
	        Button settingsButton = (Button) findViewById(R.id.SettingsButton);
	        settingsButton.setOnClickListener(new View.OnClickListener() {
	            public void onClick(View view) {
	            	openSettingsDialog();
	            }
	        });
	        
	        freeStates = new HashMap<Date, Boolean>();
	        LoadSharedSettings();
	        
	        ContentResolver resolver = getContentResolver();
	        resolver.registerContentObserver(CALLSURI, false, new CallLogObserver(resolver));
        } catch (Exception ex) {
        	Log.e("CallDurationWatcherActivity.onCreate", ex.getMessage());
        }
    }
    
    private void UpdateTimer() {
		
    	try {
	    	int overallDurationMinutes = 0;
	    	SharedPreferences.Editor editor = GetSharedPreferences().edit();
	    	
	    	minutesLeft = GetSharedPreferences().getInt(getString(R.string.minutesLeft), -1);
	    	
	    	if (minutesLeft == -1)
	    		firstStart = true;
	    	
	    	if (freeMinutesSetting == -1) {
	    		String stringValue = GetSharedPreferences().getString(getString(R.string.freeMinutes), null);
	    		if (stringValue != null)
	    			freeMinutesSetting = Integer.parseInt(stringValue);
	    	}
	    	
	    	boolean contractDateChecked = GetSharedPreferences().getBoolean(getString(R.string.contractDateChecked), false);
	    	final Calendar c = Calendar.getInstance();
	        int year = GetSharedPreferences().getInt(getString(R.string.year_setting), c.get(Calendar.YEAR)); 
	        int month = GetSharedPreferences().getInt(getString(R.string.month_setting), c.get(Calendar.MONTH));
	        int day = GetSharedPreferences().getInt(getString(R.string.day_setting), c.get(Calendar.DAY_OF_MONTH));
			Date newContractStartDate = new Date(year, month, day);
			
			Date now = new Date();
			if (now.getYear() == Utils.GetCallLogFilterDate(this).getYear() 
					&& now.getMonth() == Utils.GetCallLogFilterDate(this).getMonth() 
					&& now.getDate() == Utils.GetCallLogFilterDate(this).getDate()) {
				
				if (!contractDateChecked) {
					minutesLeft = 0;
					contractDateChecked = true;
				}
			} else {
				contractDateChecked = false;
			}
			
			editor.putBoolean(getString(R.string.contractDateChecked), contractDateChecked);
	    	
	    	if (firstStart || !contractStartDate.equals(newContractStartDate)) {
		    	
	    		overallDurationMinutes = Utils.GetCallLogDuration(this);
		        
		        minutesLeft = freeMinutesSetting - overallDurationMinutes;
		        
		        firstStart = false;
		        editor.putBoolean("firstStart", firstStart);
		        
		        int progress = minutesLeft;
		        if (freeMinutesSetting < 0)
		        	progress = 0;
		        timerProgress.setProgress(freeMinutesSetting - progress);
		        
	    	} else {
	    		
	    		int newFreeMinutesSetting = -1;
	    		String freeMinutesString = GetSharedPreferences().getString(getString(R.string.freeMinutes), ""); 
	    		if (freeMinutesString != null && freeMinutesString.length() > 0) {
		    		try {
		    			newFreeMinutesSetting = Integer.parseInt(freeMinutesString);
		    		} catch (Exception ex) {
		    			
		    		}
		    	}
	    		
	    		minutesLeft = newFreeMinutesSetting - (freeMinutesSetting - minutesLeft);
	    		
	    		int progress = minutesLeft;
	            if (freeMinutesSetting < 0)
	            	progress = 0;
	            timerProgress.setMax(newFreeMinutesSetting);
	            timerProgress.setProgress(newFreeMinutesSetting - progress);
	    	}
	        
	        TextView timerview = (TextView) findViewById(R.id.TimerView);
	        timerview.setText(minutesLeft + " min");
	        timerview.refreshDrawableState();
	        
	        
	        editor.putInt(getString(R.string.minutesLeft), minutesLeft);
	        editor.commit();
    	} catch (Exception ex) {
    		Log.e("CallDurationWatcherActivity.UpdateTimer", ex.getMessage());
    	}
	}

	private SharedPreferences GetSharedPreferences() {
    	
    	return PreferenceManager.getDefaultSharedPreferences(this);
    }
    
    private void LoadSharedSettings() {
    	
    	try {
    		
    		firstStart = GetSharedPreferences().getBoolean("firstStart", true);
    		final Calendar c = Calendar.getInstance();
            int year = GetSharedPreferences().getInt(getString(R.string.year_setting), c.get(Calendar.YEAR)); 
            int month = GetSharedPreferences().getInt(getString(R.string.month_setting), c.get(Calendar.MONTH));
            int day = GetSharedPreferences().getInt(getString(R.string.day_setting), c.get(Calendar.DAY_OF_MONTH));
    		contractStartDate = new Date(year, month, day);
    		
	    	minutesLeft = GetSharedPreferences().getInt(getString(R.string.minutesLeft), -1);
	    	String freeMinutesString = GetSharedPreferences().getString(getString(R.string.freeMinutes), ""); 
	    	freeMinutesSetting = -1;
	    	if (freeMinutesString != null && freeMinutesString.length() > 0) {
	    		try {
	    			freeMinutesSetting = Integer.parseInt(freeMinutesString);
	    		} catch (Exception ex) {
	    			
	    		}
	    	}
	    	TextView timerview = (TextView) findViewById(R.id.TimerView);
	    	
	    	if (minutesLeft == -1 && freeMinutesSetting == -1) {
	    		
	    		timerview.setText("FREE MINUTES");
	    	} else if (minutesLeft == -1) {
	    		
	    		timerview.setText(freeMinutesSetting + " min");
	    	} else {
	    		
	    		timerview.setText(minutesLeft + " min");
	    	}
	    	
	    	timerProgress = (ProgressBar) findViewById(R.id.TimerProgressBar);
	    	timerProgress.setMax(freeMinutesSetting);
	    	
    	} catch (Exception ex) {
    		Log.e("CallDurationWatcherActivity.LoadSharedSettings", ex.getMessage());
    	}
    }
    
    private void UpdateCallHistory() {
		
    	Cursor mCallCursor = CallLogHelper.getCallCursor(this);
    	
    	try {
    		
	    	freeStates.clear();
	    	
			ListAdapter adapter = new CallLogListAdapter(
					this, 
					R.layout.call_list_item, 
					mCallCursor, 
					new String[] { CallLog.Calls.CACHED_NAME, CallLog.Calls.DATE, CallLog.Calls.NUMBER, CallLog.Calls.DURATION }, 
					new int[] { R.id.txtName, R.id.txtDate, R.id.txtNumber, R.id.txtDuration });
					
			ListView lv = (ListView) findViewById(R.id.CallList);
			lv.setAdapter(adapter);
			lv.refreshDrawableState();
    	} catch (Exception ex) {
    		Log.e("CallDurationWatcherActivity.UpdateCallHistory", ex.getMessage());
    	}
	}
    
    @Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.menu, menu);
		return true;
	}

	// This method is called once the menu is selected
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		
		openSettingsDialog();
		return true;
	}
	
	private void openSettingsDialog() {
		Intent i = new Intent(CallDurationWatcherActivity.this, Preferences.class);
		startActivity(i);
	}
	
	@Override
	public void onOptionsMenuClosed(Menu menu) {
		
		super.onOptionsMenuClosed(menu);
	}
	
	@Override
	protected void onResume() {
		
		UpdateTimer();
		LoadSharedSettings();
		UpdateCallHistory();
		
		super.onResume();
	}
		
	public class CallLogObserver extends ContentObserver {

		private ContentResolver resolver;
		SharedPreferences prefs;
		
		public CallLogObserver(ContentResolver contentResolver) {
			super(null);
			
			resolver = contentResolver;
			prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
		}

		@Override public boolean deliverSelfNotifications() { 
	        return false; 
		}

	    public void logCallLog()
	    {
	        
	        Cursor c = CallLogHelper.getCallCursor(resolver, getApplicationContext());
	        while (c.moveToNext())
	        {
	            Date callTime = new Date(c.getLong(0));
	            //String name = c.getString(1);
	            //long duration = c.getLong(2);
	            String number = c.getString(3);
	            String type = c.getString(4);
	            Log.i("CallLog","type: " + type + "Call to number: " + number + ", registered at: " + callTime);
	        }
	    }

	    private void UpdateFreeMinutesLeft() {
			
			Cursor cursor = CallLogHelper.getCallCursor(resolver, getApplicationContext());
			
			if (cursor == null)
				return;
			
			try {
			
				if (cursor.moveToFirst()) {
					
					if (!Utils.IsCallFree(cursor.getString(3), getApplicationContext()))
						return;
					
					long duration = cursor.getLong(2);
					
					int minutesLeft = prefs.getInt(getString(R.string.minutesLeft), -1);
					if (minutesLeft == -1)
						return;
					SharedPreferences.Editor editor = prefs.edit();
					editor.putInt(getString(R.string.minutesLeft), minutesLeft - Utils.GetMinutes(duration));
					editor.commit();
				}
			} catch (Exception ex) {
				Log.e("CallLogObserver.UpdateFreeMinutesLeft", ex.getMessage());
			}
		}
	    
	    public void onChange(boolean selfChange) {
	        
	    	super.onChange(selfChange);
	        Log.d("PhoneService", "StringsContentObserver.onChange( " + selfChange + ")");
	        //logCallLog();
	        UpdateFreeMinutesLeft();
	    }
	}
	
	public class CallLogListAdapter extends SimpleCursorAdapter {

		private Context ctx;
		
		public CallLogListAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
			
			super(context, layout, c, from, to);
		}
		
		@Override
		public void bindView(View view, Context context, Cursor cursor) {
			
			try {
				
				Date callTime = new Date(cursor.getLong(CallLogFields.DATE.ordinal()));
	            String name = cursor.getString(CallLogFields.NAME.ordinal());
	            long duration = cursor.getLong(CallLogFields.DURATION.ordinal());
	            int minutes = Utils.GetMinutes(duration);
	            String number = cursor.getString(CallLogFields.NUMBER.ordinal());
	            
	            boolean isFree = Utils.IsCallFree(number, getApplicationContext());
	            freeStates.put(callTime, isFree);
	            CheckBox freeCheck = (CheckBox) view.findViewById(R.id.freeCheck);
	            freeCheck.setTag(callTime);
	            freeCheck.setChecked(isFree);
	            
	            freeCheck.setOnCheckedChangeListener( new OnCheckedChangeListener() {
					
					@Override
					public void onCheckedChanged(CompoundButton cbutton, boolean checkState) {
						
						ArrayList<String> saveList = new ArrayList<String>(Utils.GetFreeMinutesAreaCodes(getApplicationContext()));
						TableRow row = (TableRow) cbutton.getParent();
						try {
							Date callTime = (Date) cbutton.getTag();
							boolean state = freeStates.get(callTime);
							if (state == checkState)
								return;
						} catch (Exception ex) {
							
						}
						
						TextView txtNumber = (TextView) row.findViewById(R.id.txtNumber);
						SharedPreferences preferences = GetSharedPreferences();
						ctx = getApplicationContext();
						int minutesLeft = preferences.getInt(ctx.getString(R.string.minutesLeft), 0);
						
						String number = txtNumber.getText().toString();
						
						if (checkState && !saveList.contains(number)) {
							saveList.add(number);
							minutesLeft = minutesLeft - Utils.GetCallLogNumberDuration(ctx.getApplicationContext(), number);
						}
						
						if (!checkState && saveList.contains(number)) {
							saveList.remove(number);
							minutesLeft = minutesLeft + Utils.GetCallLogNumberDuration(ctx.getApplicationContext(), number);
						}
						
						SharedPreferences.Editor editor = preferences.edit();
				    	editor.putString(ctx.getString(R.string.savedAreaCodes), Utils.JoinAreaCodes(saveList));
				    	editor.putInt(ctx.getString(R.string.minutesLeft), minutesLeft);
				    	editor.commit();
				    	
				    	CallDurationWatcherActivity.this.UpdateTimer();
				    	CallDurationWatcherActivity.this.UpdateCallHistory();
					}
				});
	            
	            TextView txtName = (TextView) view.findViewById(R.id.txtName);
	            txtName.setText(name);
	            
	            TextView txtDate = (TextView) view.findViewById(R.id.txtDate);
	            txtDate.setText(callTime.toLocaleString());
	            
	            TextView txtPhone = (TextView) view.findViewById(R.id.txtNumber);
	            txtPhone.setText(number);
	            
	            TextView txtDuration = (TextView) view.findViewById(R.id.txtDuration);
	            txtDuration.setText(minutes + " min");
				
			} catch (Exception ex) {
				Log.e("CallLogListAdapter.bindView", ex.getMessage());
			}
		}
	}
}